// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
@file:JvmName("ModuleAssertions")

package com.intellij.testFramework.utils.module

import com.intellij.openapi.module.Module
import com.intellij.openapi.project.Project
import com.intellij.platform.backend.workspace.workspaceModel
import com.intellij.platform.workspace.jps.entities.ModuleEntity
import com.intellij.platform.workspace.jps.entities.ModuleId
import com.intellij.platform.workspace.storage.EntityStorage
import com.intellij.platform.workspace.storage.entities
import com.intellij.platform.workspace.storage.impl.url.toVirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrl
import com.intellij.platform.workspace.storage.url.VirtualFileUrlManager
import org.junit.jupiter.api.Assertions
import java.nio.file.Path

fun assertModules(project: Project, vararg expectedNames: String) {
  assertModules(project, expectedNames.asList())
}

fun assertModules(project: Project, expectedNames: List<String>) {
  val storage = project.workspaceModel.currentSnapshot
  assertModules(storage, expectedNames)
}

fun assertModules(storage: EntityStorage, vararg expectedNames: String) {
  assertModules(storage, expectedNames.asList())
}

fun assertModules(storage: EntityStorage, expectedNames: List<String>) {
  val actualNames = storage.entities<ModuleEntity>().map { it.name }.toList()
  assertEqualsUnordered(expectedNames, actualNames)
}

fun assertModulesContains(project: Project, vararg expectedNames: String) {
  assertModulesContains(project, expectedNames.asList())
}

fun assertModulesContains(project: Project, expectedNames: List<String>) {
  val storage = project.workspaceModel.currentSnapshot
  assertModulesContains(storage, expectedNames)
}

fun assertModulesContains(storage: EntityStorage, vararg expectedNames: String) {
  assertModulesContains(storage, expectedNames.asList())
}

fun assertModulesContains(storage: EntityStorage, expectedNames: List<String>) {
  val actualNames = storage.entities<ModuleEntity>().map { it.name }.toList()
  assertContains(expectedNames, actualNames)
}

fun assertContentRoots(module: Module, vararg expectedRoots: Path) {
  assertContentRoots(module, expectedRoots.asList())
}

fun assertContentRoots(module: Module, expectedRoots: List<Path>) {
  assertContentRoots(module.project, module.name, expectedRoots)
}

fun assertContentRoots(project: Project, moduleName: String, vararg expectedRoots: Path) {
  assertContentRoots(project, moduleName, expectedRoots.asList())
}

fun assertContentRoots(project: Project, moduleName: String, expectedRoots: List<Path>) {
  val workspaceModel = project.workspaceModel
  val storage = workspaceModel.currentSnapshot
  val virtualFileUrlManager = workspaceModel.getVirtualFileUrlManager()
  assertContentRoots(virtualFileUrlManager, storage, moduleName, expectedRoots)
}

fun assertContentRoots(virtualFileUrlManager: VirtualFileUrlManager, storage: EntityStorage, moduleName: String, vararg expectedRoots: Path) {
  assertContentRoots(virtualFileUrlManager, storage, moduleName, expectedRoots.asList())
}

fun assertContentRoots(virtualFileUrlManager: VirtualFileUrlManager, storage: EntityStorage, moduleName: String, expectedRoots: List<Path>) {
  val moduleId = ModuleId(moduleName)
  val moduleEntity = storage.resolve(moduleId)
  Assertions.assertNotNull(moduleEntity) {
    "The module '$moduleName' doesn't exist"
  }
  assertContentRoots(virtualFileUrlManager, moduleEntity!!, expectedRoots)
}

fun assertContentRoots(virtualFileUrlManager: VirtualFileUrlManager, moduleEntity: ModuleEntity, vararg expectedRoots: Path) {
  assertContentRoots(virtualFileUrlManager, moduleEntity, expectedRoots.asList())
}

fun assertContentRoots(virtualFileUrlManager: VirtualFileUrlManager, moduleEntity: ModuleEntity, expectedRoots: List<Path>) {
  val expectedRootUrls = expectedRoots.map { it.normalize().toVirtualFileUrl(virtualFileUrlManager) }
  assertContentRoots(moduleEntity, expectedRootUrls)
}

fun assertContentRoots(moduleEntity: ModuleEntity, vararg expectedRoots: VirtualFileUrl) {
  assertContentRoots(moduleEntity, expectedRoots.asList())
}

fun assertContentRoots(moduleEntity: ModuleEntity, expectedRoots: List<VirtualFileUrl>) {
  val actualRoots = moduleEntity.contentRoots.map { it.url }
  assertEqualsUnordered(expectedRoots, actualRoots)
}